package com.bj58.analysis.tools;

import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;

import com.bj58.analysis.tools.common.CookieIdUtils;
import com.bj58.analysis.tools.common.EncryptHelper;
import com.bj58.analysis.tools.common.GetObjectToClassUtils;
import com.bj58.analysis.tools.common.TrackUrlUtils;
import com.bj58.analysis.tools.common.URLDecodeUtils;
import com.bj58.analysis.tools.common.bean.LogBean;
import com.bj58.analysis.tools.original.bean.OriginalTrackBean;

/**
 * @description track原始日志解析逻辑类
 * @author tzc
 *
 */
public class OriginalTrackAnalysis extends CommonAnalysis {

	@Override
	protected LogBean analysis(String logLine) {
		OriginalTrackBean bean = null;
		if (StringUtils.isNotBlank(logLine)) {
			Map<String, String> map = null;
			String[] logLines = logLine.split("\001", -1);
			if (logLines.length >= 14) {
				map = parserOfNV(logLines);// 新版日志解析
			} else {
				map = parserOfOV(logLine);// 旧版日志解析
			}

			if (map != null && map.size() != 0) {
				Object obj = GetObjectToClassUtils.getObjectByMap(
						OriginalTrackBean.class, map);
				if (obj != null)
					bean = (OriginalTrackBean) obj;
			}
		}

		return bean;
	}

	// 新版日志解析
	private Map<String, String> parserOfNV(String[] logLines) {
		Map<String, String> map = new HashMap<String, String>();

		String cookieId = logLines[0].trim();
		if (StringUtils.isBlank(cookieId) || cookieId.equals("-")
				|| cookieId.length() < 10) {
			cookieId = CookieIdUtils.getCookieIdOfRand();
		}
		map.put("cookieID", cookieId);// cookieId
		map.put("epoch", logLines[1]);
		map.put("userIp", logLines[2]);

		// 解析请求串
		String[] requestStrs = logLines[5].split("empty.js.gif\\?");
		if (requestStrs.length >= 2) {
			String requestStr = requestStrs[1].split(" ")[0].trim();
			parserRequestStr(requestStr, map);
		}

		// 请求状态
		String status = logLines[6].trim();
		if (StringUtils.isNotBlank(status))
			map.put("status", status);

		// 解析url和站内关键词
		String url = logLines[8].trim();
		// 如果cookieid和url都为空，则当垃圾数据处理
		if (StringUtils.isNotBlank(url))
			parserUrl(url, map);

		// 解析UA头
		String userAgent = logLines[9].trim();
		if (StringUtils.isNotBlank(userAgent)) {
			map.put("userAgent", userAgent);
		}

		// 登陆用户id
		String loginUid = logLines[logLines.length - 1].trim();
		if (StringUtils.isNotBlank(loginUid) && !loginUid.equals("-"))
			map.put("loginUid", loginUid);

		return map;
	}

	// 旧版日志解析逻辑
	private Map<String, String> parserOfOV(String logLine) {
		Map<String, String> map = null;
		String[] logs = logLine.split("\"");
		if (logs.length >= 4) {
			map = new HashMap<String, String>();
			String[] preStr = logs[0].split(" ", -1);// 按空格切分第一段
			if (preStr.length >= 3) {
				String epoch = preStr[1].trim();
				String userIp = preStr[2].trim();

				String cookieId = preStr[0].trim();
				if (StringUtils.isBlank(cookieId) || cookieId.equals("-")
						|| cookieId.length() < 10) {
					cookieId = CookieIdUtils.getCookieIdOfRand();
				}
				map.put("cookieID", cookieId);// cookieId
				map.put("epoch", epoch);
				map.put("userIp", userIp);
			}

			// 解析请求串
			String[] requestStrs = logs[0].split("empty.js.gif\\?");
			if (requestStrs.length >= 2) {
				String requestStr = requestStrs[1].split(" ")[0].trim();
				parserRequestStr(requestStr, map);
			}

			// 请求状态
			String status = logs[1].trim();
			if (StringUtils.isNotBlank(status))
				map.put("status", status);

			// 解析url和站内关键词
			String url = logs[3].trim();
			// 如果cookieid和url都为空，则当垃圾数据处理
			if (StringUtils.isNotBlank(url))
				parserUrl(url, map);

			// 解析UA头
			if (logs.length - 4 >= 0) {
				String ua = logs[logs.length - 4];
				if (StringUtils.isNotBlank(ua)) {
					map.put("userAgent", ua);
				}
			}

			// 登陆用户id
			String[] loginUids = logs[logs.length - 1].split("\\|", 2);
			if (loginUids.length == 2) {
				String loginUid = loginUids[1].trim();
				if (StringUtils.isNotBlank(loginUid) && !loginUid.equals("-"))
					map.put("loginUid", loginUid);
			}
		}
		return map;
	}

	// 解析url和站内关键词
	private void parserUrl(String url, Map<String, String> map) {
		if (StringUtils.isNotBlank(url)) {
			try {
				url = URLDecodeUtils.parser(url);
			} catch (Exception e) {
				url = URLDecodeUtils.getSearchEngines(url);
			}
			String inkword = getWordByUrl(url);
			if (StringUtils.isBlank(inkword)) {
				// 如果url上不存在，则从
				String referer = map.get("referrer");
				if (StringUtils.isNotBlank(referer)) {
					inkword = getWordByUrl(referer);
					if (StringUtils.isNotBlank(inkword)) {
						map.put("inKWord", inkword);
					}
				}
			} else {
				map.put("inKWord", inkword);
			}
			map.put("url", url);
		}
	}

	// 从url中获取关键词key
	private String getWordByUrl(String url) {
		String tmpWord = null;
		String domain = URLDecodeUtils.getSearchEngines(url);
		if (StringUtils.isNotBlank(domain)) {
			String pattern = "(&|\\?)(key=)[^&]+";
			Pattern p_a = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
			Matcher m_a = p_a.matcher(url);
			while (m_a.find()) {
				String a = m_a.group();
				if (a.length() > 5) {// key=的长度{
					a = a.substring(5, a.length());
					if (StringUtils.isNotBlank(a)) {
						tmpWord = a;
						break;
					}
				}
			}
		}
		return tmpWord;
	}

	// 请求串进行解析
	private void parserRequestStr(String requestStr, Map<String, String> map) {
		if (StringUtils.isNotBlank(requestStr)) {
			StringTokenizer strRequestParameters = new StringTokenizer(
					requestStr, "&");
			while (strRequestParameters.hasMoreTokens()) {
				String tmpString = strRequestParameters.nextToken().trim();
				parserParam(tmpString, map);
			}
		}
	}

	// 对每个参数进行解析
	private void parserParam(String param, Map<String, String> map) {
		if (getFlagOfParam(param, "site_name=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				map.put("siteName", tmpValue);
			}
		} else if (getFlagOfParam(param, "version=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				map.put("pageVersion", tmpValue);
			}
		} else if (getFlagOfParam(param, "post_count=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				map.put("postCount", tmpValue);
			}
		} else if (getFlagOfParam(param, "window_size=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				map.put("windowSize", tmpValue);
			}
		} else if (getFlagOfParam(param, "userid=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				map.put("userId", tmpValue);
			}
		} else if (getFlagOfParam(param, "loadtime=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				map.put("loadTime", tmpValue);
			}
		} else if (getFlagOfParam(param, "trackURL=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				String trackUrl = parserTrackUrl(tmpValue, map);
				if (StringUtils.isNotBlank(trackUrl))
					map.put("trackUrl", trackUrl);
			}

		} else if (getFlagOfParam(param, "_ga_utma=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				map.put("gautma", tmpValue);
			}
		} else if (getFlagOfParam(param, "_trackParams=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				try {
					tmpValue = URLDecoder.decode(tmpValue, "utf-8");
					map.put("unitParams", tmpValue);
				} catch (Exception e) {
					// e.printStackTrace();
				}
			}
		} else if (getFlagOfParam(param, "smsc=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				try {
					tmpValue = EncryptHelper.desDecrypt(tmpValue);
					map.put("queryParams", tmpValue);
				} catch (Exception e) {
					// e.printStackTrace();
				}
			}
		} else if (getFlagOfParam(param, "referrer=")) {
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				try {
					tmpValue = URLDecodeUtils.parser(tmpValue);
				} catch (Exception e) {
					tmpValue = URLDecodeUtils.getSearchEngines(tmpValue);
				}
				if (StringUtils.isNotBlank(tmpValue)) {
					map.put("referrer", tmpValue);

					String refdomain = URLDecodeUtils.getDomain(tmpValue);
					map.put("refDomain", refdomain);
				}
			}
		} else if (getFlagOfParam(param, "supplycount.")) {// 特殊参数集合
			String tmpValue = getLastParam(param);
			if (StringUtils.isNotBlank(tmpValue)) {
				String[] params = param.split("=", 2);
				String[] keys = params[0].split(".", 2);
				if (keys.length == 2) {// supplycount.sortid
					String tmpKey = keys[1];
					String tmpSupplycount = map.get("supplyCount");
					if (StringUtils.isNotBlank(tmpSupplycount)) {
						try {
							Map<String, String> tmpMap = new HashMap<String, String>();
							tmpMap.put(tmpKey, tmpValue);
							JSONObject json = JSONObject
									.fromObject(tmpSupplycount);
							json.putAll(tmpMap);
							map.put("supplyCount", json.toString());
						} catch (Exception e) {// 如果无法正确解析，但需保留pv
							// e.printStackTrace();
						}
					} else {
						try {
							Map<String, String> tmpMap = new HashMap<String, String>();
							tmpMap.put(tmpKey, tmpValue);
							JSONObject json = JSONObject.fromObject(tmpMap);
							map.put("supplyCount", json.toString());
						} catch (Exception e) {
							// e.printStackTrace();
						}
					}
				}
			}
		}
	}

	// 解析trackurl
	private String parserTrackUrl(String trackUrl, Map<String, String> map) {
		String tmpline = null;
		trackUrl = TrackUrlUtils.formatTrackUrl(trackUrl);
		if (StringUtils.isNotBlank(trackUrl)) {
			JSONObject obj = null;
			try {
				obj = JSONObject.fromObject(trackUrl);
			} catch (Exception e) {
				return null;
			}// 以上解析方式能正常解析99%的数据，对于极少的个别错误数据直接抛弃trackurl

			if (obj != null) {
				boolean flag = obj.containsKey("init_refer");
				if (flag) {
					String init_refer = obj.getString("init_refer");
					if (StringUtils.isNotBlank(init_refer)) {

						// 获取站外关键词,此处需要注意，init_refer从trackurl中提取出来需要先
						//进行解码
						String outWord = URLDecodeUtils.getWord(init_refer);
						if (StringUtils.isNotBlank(outWord)) {
							outWord = outWord.replace(".", "");
							map.put("outKWord", outWord);
						}

						obj.put("init_refer", init_refer);
					}
				}

				// catePath解析
				boolean cateFlag = obj.containsKey("cate");
				if (cateFlag) {
					String catePath = obj.getString("cate");
					if (StringUtils.isNotBlank(catePath))
						map.put("catePath", catePath);
				}

				// areaPath解析
				boolean areaFlag = obj.containsKey("area");
				if (areaFlag) {
					String areaPath = obj.getString("area");
					areaPath = URLDecodeUtils.parser(areaPath);
					if (StringUtils.isNotBlank(areaPath)) {
						if (areaPath.contains("?"))
							areaPath = "";
						obj.put("area", areaPath);
						map.put("areaPath", areaPath);
					}
				}

				// infoId
				boolean infoidFlag = obj.containsKey("infoid");
				if (infoidFlag) {
					String infoId = obj.getString("infoid");
					if (StringUtils.isNotBlank(infoId))
						map.put("infoId", infoId);
				}

				// infoType
				boolean infotypeFlag = obj.containsKey("infotype");
				if (infotypeFlag) {
					String infoType = obj.getString("infotype");
					if (StringUtils.isNotBlank(infoType))
						map.put("infoType", infoType);
				}

				// userType
				boolean usertypeFlag = obj.containsKey("usertype");
				if (usertypeFlag) {
					String userType = obj.getString("usertype");
					if (StringUtils.isNotBlank(userType))
						map.put("userType", userType);
				}

				// pageType
				boolean pageTypeFlag = obj.containsKey("pagetype");
				if (pageTypeFlag) {
					String pageType = obj.getString("pagetype");
					if (StringUtils.isNotBlank(pageType)) {
						map.put("pageType", pageType);
					} else {
						map.put("pageType", "other");
					}
				}

				// 兼容旧版工具类
				tmpline = obj.toString();
				tmpline = tmpline.replaceAll("'", "");
				tmpline = tmpline.replaceAll("\"", "'");
			}
		}
		return tmpline;
	}

	// 对每个参数进行判断是否符合规则
	private boolean getFlagOfParam(String param, String paramName) {
		return param.indexOf(paramName) == 0 && !param.equals(paramName);
	}

	// 分隔参数
	private String getLastParam(String param) {
		String tmpParam = null;
		if (StringUtils.isNotBlank(param)) {
			String[] params = param.split("=", 2);
			if (params.length == 2 && StringUtils.isNotBlank(params[1])
					&& !params[1].equals("NA"))
				tmpParam = params[1];
		}
		return tmpParam;
	}

}
